import { get, set } from 'lodash'
const { ipcRenderer } = window.electron

export default function createPersistedStatePlugin(options) {
  return (store) => {
    const defaultOptions = {
      paths: null,
      key: 'electron-vuex'
    }
    const { paths, key } = Object.assign(defaultOptions, options)
    if (paths) {
      if (!Array.isArray(paths)) {
        throw new Error('paths must be an array or null')
      }
      if (paths.length === 0) {
        return
      }
    }

    let watchers = []

    ipcRenderer.on('state-changed', (event, persistedState) => {
      // console.log('state-changed', persistedState)
      if (watchers?.length) {
        watchers.forEach((watcher) => {
          watcher()
        })
      }
      // 根据持久化的状态更新 store
      let newState
      if (!paths) {
        newState = persistedState
      } else {
        const prevState = store.state
        paths.forEach((path) => {
          set(prevState, path, get(persistedState, path))
        })
        newState = prevState
      }
      store.replaceState(newState)
      // 重新开启监听 store 的变化
      watchers = createWatcher(store, key, paths)
    })

    // 同步方式
    const data = ipcRenderer.sendSync('get-state', { key })

    let state
    const originalState = store.state
    if (data) {
      if (paths) {
        paths.forEach((path) => {
          set(originalState, path, get(data, path, get(originalState, path)))
        })
        state = originalState
      } else {
        state = data
      }
      store.replaceState(state)
    } else {
      const newState = getPersistedState(originalState, paths)
      ipcRenderer.send('set-state', { key, state: newState })
    }

    // 监听 store 的变化
    watchers = createWatcher(store, key, paths)
  }
}

// 获取持久化的状态属性
function getPersistedState(state, paths) {
  if (!paths) {
    return state
  }
  return paths.reduce((acc, path) => {
    set(acc, path, get(state, path))
    return acc
  }, {})
}

// 创建监听器
function createWatcher(store, key, paths) {
  if (!paths) {
    const watcher = store.watch(
      (state) => {
        return state
      },
      (arg) => {
        ipcRenderer.send('set-state', { key, state: arg })
      },
      {
        deep: true
      }
    )
    return [watcher]
  } else {
    return paths.map((path) => {
      return store.watch(
        (state) => {
          return get(state, path)
        },
        () => {
          const newState = getPersistedState(store.state, paths)
          ipcRenderer.send('set-state', { key, state: newState })
        },
        {
          deep: true
        }
      )
    })
  }
}
